
#include "Document.h"

const double PI = 22.0/7.0;
const double PI2 = PI/2.0;

int Document::Create( int width, int height )
{
	_width = width; _height = height;

	// Create our bitmap
	BITMAPINFO binf = {0};
	binf.bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
	binf.bmiHeader.biWidth = width;
	binf.bmiHeader.biHeight = -height;
	binf.bmiHeader.biPlanes = 1;
	binf.bmiHeader.biBitCount = 32;
	binf.bmiHeader.biCompression = BI_RGB;
	binf.bmiHeader.biSizeImage = 0;
	pBmpBits = NULL;
	hBmp = CreateDIBSection( NULL, &binf, DIB_RGB_COLORS, &pBmpBits, NULL, 0 );
	if (!hBmp) {
		MessageBoxW( NULL, L"Error while create DIBSection", L"Draw", MB_OK|MB_ICONERROR );
		return 0;
	}
	bufDC = CreateCompatibleDC( NULL );
	SelectObject( bufDC, hBmp );

	stride = width * 4;
	
	xmin = new int[_height];
	xmax = new int[_height];

	return 1;
}

Document::~Document(void)
{
	DeleteObject( hBmp );
	DeleteDC( bufDC );
}

void Document::BeginStroke( int x, int y ) {
	stroke = STROKE_START;
}

void Document::EndStroke() {
	if( stroke == STROKE_NONE ) return;
	stroke = STROKE_NONE;
}

/*
////p3-------------p4
////|              |
////| width1       | width2
////|              |
////x1,y1--------x2,y2
////|              |
////|              |
////|              |
////p1-------------p2
*/
void Document::DrawLine( int x1, int y1, int x2, int y2, double width1, double width2 ) {
	double w12 = width1/2.0;
	double w22 = width2/2.0;

	stroke = STROKE_MIDDLE;
	double angle = atan2( (double)(y2-y1), (double)(x2-x1) );
	double p1x = x1 + w12 * cos( angle + PI2 );
	double p1y = y1 + w12 * sin( angle + PI2 );
	
	double p2x = x2 + w22 * cos( angle + PI2 );
	double p2y = y2 + w22 * sin( angle + PI2 );
	
	double p3x = x1 + w12 * cos( angle - PI2 );
	double p3y = y1 + w12 * sin( angle - PI2 );

	double p4x = x2 + w22 * cos( angle - PI2 );
	double p4y = y2 + w22 * sin( angle - PI2 );

	for( int y=0;y<_height;y++ ) {
		xmin[y] = _width;
		xmax[y] = -1;
	}
	ymin = _height;
	ymax - -1;

	ScanEdge( p1x, p1y, p2x, p2y );
	ScanEdge( p2x, p2y, p4x, p4y );
	ScanEdge( p4x, p4y, p3x, p3y );
	ScanEdge( p3x, p3y, p1x, p1y );

	// render scanlines
	for( int y=ymin; y<=ymax; y++ )
		RenderHLine( y, xmin[y], xmax[y] );
}

void Document::DrawLine( int x1, int y1, int x2, int y2 ) {
	stroke = STROKE_MIDDLE;

	int x, y, xe, ye, i;
	int dx = x2-x1;
	int dy = y2-y1;

	int dx1 = abs( dx );
	int dy1 = abs( dy );
	int px = 2*dy1 - dx1;
	int py = 2*dx1 - dy1;

	if( dy1 <= dx1 ) {
		if( dx >= 0 ) {
			x=x1;
			y=y1;
			xe=x2;
		} else {
			x=x2;
			y=y2;
			xe=x1;
		}
		PutPixel( x, y );
		for( i=0;x<xe;i++ ) {
			x++;
			if( px<0 )
				px+=2*dy1;
			else {
				if(( dx<0 && dy<0 ) || ( dx>0 && dy>0 ))
					y++;
				else
					y--;
				px+=2*(dy1-dx1);
			}
			PutPixel( x, y );
		}
	} else {
		if( dy>= 0 ) {
			x=x1;
			y=y1;
			ye=y2;
		}
		else {
			x=x2;
			y=y2;
			ye=y1;
		}
		PutPixel( x, y );
		for( i=0;y<ye;i++ ) {
			y++;
			if( py<= 0 )
				py+=2*dx1;
			else {
				if(( dx<0 && dy<0 ) || ( dx>0 && dy>0 ))
					x++;
				else
					x--;
				py+=2*(dx1-dy1);
			}
			PutPixel( x, y );
		}
	}
}
